// Copyright 2022 jeff.li. and/or its affiliates.

#pragma once

#include <fcntl.h>     /* for open */
#include <sys/stat.h>  /* for open */
#include <sys/types.h> /* for open */
#include <unistd.h>    /* for lseek and write */

#include <string>

#include <tbir/runtime/container/string.h>
#include <tbir/runtime/container/string_view.h>

namespace tbir::runtime {

    class FileReader {
        struct ByteBuffer {
            char *data = nullptr;
            size_t capacity = 0;
            size_t position = 0;
            size_t limit = 0;
        };

    public:
        explicit FileReader(string_view path, bool keep_newline = false);

        virtual ~FileReader();

    public:
        bool ReadLine(std::string &line) {
            const char *out = nullptr;
            size_t len = 0;
            bool r = ReadLine(&out, &len);
            line = std::move(std::string(out, len));
            return r;
        }

        bool ReadLine(const char **line, size_t *len);

        inline bool IsLastLine() const {
            return _last_line;
        }

        String Read(int64_t size);

    private:
        bool readLineFromBuffer(const char **line, size_t *len);

    private:
        int _fd;
        ByteBuffer _buffer;
        std::string _path;
        bool _last_line;
        static size_t _s_buf_size;
        bool _keep_newline = false;
    };

}  // namespace tbir::runtime
